"""
Python 有两种错误很容易辨认：语法错误和异常。
Python assert（断言）用于判断一个表达式，在表达式条件为 false 的时候触发异常

Python 程序的语法是正确的，在运行它的时候，也有可能发生错误。运行期检测到的错误被称为异常。
大多数的异常都不会被程序处理，都以错误信息的形式展现在这里

1.异常处理
try/except 异常捕捉可以使用 try/except 语句。

一个 try 语句可能包含多个except子句，分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的 try 子句中的异常进行处理，而不是其他的 try 的处理程序中的异常。
一个except子句可以同时处理多个异常，这些异常将被放在一个括号里成为一个元组，例如:
except (RuntimeError, TypeError, NameError):
    pass

2.抛出异常
raise [Exception [, args [, traceback]]]

3.assert（断言）用于判断一个表达式，在表达式条件为 false 的时候触发异常

4.with 语句用于异常处理，封装了 try…except…finally 编码范式，提高了易用性
with 语句使代码更清晰、更具可读性， 它简化了文件流等公共资源的管理
"""


# 演示异常捕捉，写法1
def excpt_m1():
    #
    try:
        a = 10 / 0
        print("前面的代码出现异常，我不会打印")
    except ZeroDivisionError:  # 捕捉多个异常(RuntimeError, TypeError, NameError)
        print("出现异常了，0 不能做除数")


# 演示异常捕捉，写法2
# 该写法可以避免出现一些意想不到的异常，而 except 又无法捕获的异常，适合做善后工作如打印日志记录一下，
def excpt_m2():
    #
    try:
        a = 1 + 1
        print(f'正常运行: 1+1={a}')
    except ZeroDivisionError:
        print("出现异常了，0 不能做除数")
    else:
        print("前面的try代码没有出现意外问题，我来通知，打印日志")


# 演示异常捕捉，写法3 finally 不管前面代码是否有异常，我都会执行里面的代码
def excpt_m3():
    #
    try:
        a = 1 + 1
        print(f'正常运行: 1+1={a}')
    except ZeroDivisionError:
        print("出现异常了，0 不能做除数")
    finally:
        print("不管前面代码是否有异常，我都会执行")


# raise 抛出异常示例
def excpt_m4():
    #
    try:
        a = 1 + 1
        print(f'正常运行: 1+1={a}')
        # 主动抛出一个异常
        raise ZeroDivisionError("以上代码没有异常，就是要抛一个异常给你")
    except ZeroDivisionError as ex:
        print("哦豁，出异常了,异常提示信息: ", ex)
    finally:
        print("不管前面代码是否有异常，我都会执行")


# raise 抛出异常示例
def excpt_m5():
    #
    try:
        a = 1 + 1
        print(f'正常运行: 1+1={a}')
        # 主动抛出一个异常
        raise ZeroDivisionError("以上代码没有异常，就是要抛一个异常给你")
    except ZeroDivisionError as ex:
        print("哦豁，出异常了,异常提示信息: ", ex)
    else:
        print("前面的代码没有出现问题")
    finally:
        print("不管前面代码是否有异常，我都会执行,用于做一些善后工作，如file.close()")


# 自定义一个异常 继承基类Exception
class Myex(Exception):

    def __init__(self, msg) -> None:
        self.msg = msg

    def __str__(self) -> str:
        return str(self.msg)


# raise 抛出自定义异常示例
def excpt_m6():
    #
    try:
        a = 1 + 1
        print(f'正常运行: 1+1={a}')
        # 主动抛出一个异常
        raise Myex("这是异常提示信息")
    except Myex as ex:  # 提取异常信息给到变量ex
        print("哦豁，出异常了,提示信息: ", ex)


# assert 断言使用, 语法格式 assert expression
def excpt_m7(p1):
    #
    try:
        assert p1, "断言提示信息"  # p1传0即为false，则会抛出异常，提示信息可选 （条件为 false 触发异常）
    except AssertionError as ex:  # 提取异常信息给到变量ex
        print("哦豁，出异常了,提示信息: ", ex)
    finally:
        print("不管前面代码是否有异常，我都会执行")

def with_m1():
    """
    file = open('doc/testfile.txt', 'w')
    try:
        file.write('hello world')
    finally:
        file.close()
    """
    # 与以上代码等效，with 帮助进行了file.close 操作
    with open('doc/testfile.txt', 'w') as file:
        file.write('hello world !')


if __name__ == '__main__':
    # excpt_m1()
    # excpt_m2()
    # excpt_m3()
    # excpt_m4()
    # excpt_m5()
    # excpt_m6()
    excpt_m7(0)
